package com.genntii.examManager.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.genntii.examManager.common.constant.CommonConstant;
import com.genntii.examManager.common.exception.BaseException;
import com.genntii.examManager.common.exception.ExamNotFoundException;
import com.genntii.examManager.common.result.PageResult;
import com.genntii.examManager.domain.dto.VocabulariesDTO;
import com.genntii.examManager.domain.entity.*;
import com.genntii.examManager.domain.question.dto.ExamResult;
import com.genntii.examManager.domain.question.dto.TopicDTO;
import com.genntii.examManager.domain.question.dto.VocabularyDTO;
import com.genntii.examManager.domain.question.mongo.Vocabularies;
import com.genntii.examManager.domain.vo.Exam4tVO;
import com.genntii.examManager.domain.vo.ExamComplete;
import com.genntii.examManager.domain.vo.ExamRecordVO;
import com.genntii.examManager.domain.vo.ExamVO;
import com.genntii.examManager.mapper.*;
import com.genntii.examManager.service.ExamRecordService;
import jakarta.annotation.Resource;
import org.springframework.data.mongodb.core.BulkOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

@Service
public class ExamRecordServiceImpl extends ServiceImpl<ExamRecordMapper, ExamRecord> implements ExamRecordService {

    @Resource
    private ExamRecordMapper examRecordMapper;

    @Resource
    private ExamMapper examMapper;

    @Resource
    private TeacherMapper teacherMapper;

    @Resource
    private MongoTemplate mongoTemplate;

    @Resource
    private CourseMapper courseMapper;

    @Resource
    private UserMapper userMapper;

    @Override
    @Transactional
    public void grading(Long examId, ArrayList<VocabulariesDTO> vocabulariesDTOS) {

        Map<Long,VocabulariesDTO> vocabulariesDTOMap = new HashMap<>();
        for (VocabulariesDTO vocabulariesDTO:vocabulariesDTOS){
            vocabulariesDTOMap.put(vocabulariesDTO.getUserId(), vocabulariesDTO);
        }
        ArrayList<ExamRecord> examRecordListForeach = examRecordMapper.getExamRecordListForeach(examId);
        ArrayList<Long> _idList = new ArrayList<>();
        for (ExamRecord examRecord : examRecordListForeach){
            int score = examRecord.getScore();
            ArrayList<VocabularyDTO> vocabularyDTOS = vocabulariesDTOMap.get(examRecord.getId()).getVocabularyDTOS();
            for (VocabularyDTO vocabularyDTO:vocabularyDTOS){
                score += vocabularyDTO.getGetScore();
            }
            examRecord.setType((byte) 2);
            examRecord.setScore(score);
            _idList.add(examRecord.getId());
        }
        for (ExamRecord examRecord:examRecordListForeach){
            examRecordMapper.updateById(examRecord);
        }

        List<ExamResult> examResults = mongoTemplate.find(new Query(new Criteria("_id").in(_idList)), ExamResult.class, "userResult");

        BulkOperations bulkOperations = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, ExamResult.class);
        for (ExamResult examResult:examResults){
            TopicDTO topicDTO = examResult.getTopicDTO();
            topicDTO.setVocabularyDTOS(vocabulariesDTOMap.get(examResult.getId()).getVocabularyDTOS());
            examResult.setTopicDTO(topicDTO);
            bulkOperations.updateOne(new Query(new Criteria("_id").is(examResult.getId())),
                    Update.update("topicDTO",topicDTO));
        }
        bulkOperations.execute();


    }

    @Override
    public PageResult<ExamComplete> getStudentExamCompleteStatus(Integer pageNum, Integer pageSize, Long examId) {
        ArrayList<ExamRecord> examRecords = examRecordMapper.getExamRecordList(examId,(pageNum-1)*pageSize,pageSize);
        ArrayList<ExamComplete> examCompletes = new ArrayList<>();
        ArrayList<Long> userIds = new ArrayList<>();
        for (ExamRecord examRecord : examRecords){
            userIds.add(examRecord.getUserId());
        }
        ArrayList<User> users = userMapper.selectUserBatch(userIds);
        Map<Long,User> userMap = new HashMap<>();
        for (User user:users){
            userMap.put(user.getId(),user);
        }

        for (ExamRecord examRecord:examRecords){
            examCompletes.add(ExamComplete.builder()
                    .id(examRecord.getId())
                    .userId(examRecord.getUserId())
                    .username(userMap.get(examRecord.getUserId()).getUsername())
                    .nickname(userMap.get(examRecord.getUserId()).getNickname())
                    .score(examRecord.getScore())
                    .status(examRecord.getType())
                    .completeTime(examRecord.getCommitTime())
                    .build());
        }
        return PageResult.build(examCompletes,examRecordMapper.getExamRecordCount(examId));
    }

    @Override
    public void addExam() {

    }

    @Override
    public PageResult<Vocabularies> getVocabulary(Integer pageNum, Integer pageSize, Long examId) {
        ArrayList<ExamRecord> examRecordListPage = examRecordMapper.getExamRecordListPage((pageNum - 1) * pageSize, pageSize, examId);
        ArrayList<Long> _idList = new ArrayList<>();
        for (ExamRecord examRecord:examRecordListPage){
            _idList.add(examRecord.getId());
        }
        List<Vocabularies> vocabularies = mongoTemplate.find(new Query(new Criteria("_id").in(_idList)), Vocabularies.class, "vocabulary");
        long examRecordCount = examRecordMapper.getExamRecordCount(examId);
        return PageResult.build((ArrayList<Vocabularies>) vocabularies,examRecordCount);
    }

    @Override
    public void examCommit(ExamResult examResult, Long userId) {
        if (examMapper.selectById(examResult.getExamId()) == null){
            throw new ExamNotFoundException("未找到考试");
        }

        ExamRecord examRecordByExamUserId;
        if (examResult.getTopicDTO().getVocabularyDTOS().isEmpty()){
            examRecordByExamUserId = examRecordMapper.getExamRecordByExamUserId(examResult.getExamId(), userId);
            examRecordByExamUserId.setScore(examResult.getBaseScore());
            examRecordByExamUserId.setCommitTime(examResult.getCommitTime());
            examRecordByExamUserId.setType((byte)2);
            examRecordMapper.updateById(examRecordByExamUserId);
        } else {
            examRecordByExamUserId = examRecordMapper.getExamRecordByExamUserId(examResult.getExamId(), userId);
            examRecordByExamUserId.setCommitTime(examResult.getCommitTime());
            examRecordByExamUserId.setScore(examResult.getBaseScore());
            examRecordByExamUserId.setType((byte)1);
            examRecordMapper.updateById(examRecordByExamUserId);

            mongoTemplate.insert(Vocabularies.builder()
                    ._id(examRecordByExamUserId.getId())
                    .vocabularyDTOS(examResult.getTopicDTO().getVocabularyDTOS()).build(),"vocabulary");
        }

        examResult.setId(examRecordByExamUserId.getId());
        mongoTemplate.insert(examResult,"userResult");
    }

    @Override
    public PageResult<ExamRecordVO> getExamHistory(Integer pageNum, Integer pageSize, Long userId) {
        ArrayList<ExamRecord> examRecords = examRecordMapper.getExamHistory(userId, (pageNum - 1) * pageSize, pageSize);

        ArrayList<Long> examIds = new ArrayList<>();
        for (ExamRecord examRecord:examRecords){
            examIds.add(examRecord.getExamId());
        }
        ArrayList<Exam> exams = examMapper.getExamBatch(examIds);
        Map<Long, Exam> examIdMap = new HashMap<>();
        for (Exam exam:exams){
            examIdMap.put(exam.getId(),exam);
        }
        ArrayList<Long> courseIds = new ArrayList<>();
        ArrayList<Long> teacherIds = new ArrayList<>();
        for (Exam exam:exams){
            courseIds.add(exam.getCourseId());
            teacherIds.add(exam.getTeacherId());
        }
        ArrayList<Course> courses = courseMapper.getCourseBatch(courseIds);
        ArrayList<Teacher> teachers = teacherMapper.getTacherBatch(teacherIds);

        Map<Long, Course> courseMap = new HashMap<>();
        Map<Long, Teacher> teacherMap = new HashMap<>();
        for (Teacher teacher : teachers){
            teacherMap.put(teacher.getId(),teacher);
        }
        for (Course course : courses){
            courseMap.put(course.getId(),course);
        }

        ArrayList<ExamRecordVO> examRecordVOS = new ArrayList<>();
        for (ExamRecord examRecord : examRecords){
            examRecordVOS.add(ExamRecordVO.builder()
                    .id(examRecord.getId())
                    .examId(examRecord.getExamId())
                    .courseName(courseMap.get(examIdMap.get(examRecord.getExamId()).getCourseId()).getCourseName())
                    .teacherName(teacherMap.get(examIdMap.get(examRecord.getExamId()).getTeacherId()).getName())
                    .startTime(examIdMap.get(examRecord.getExamId()).getStartTime())
                    .commitTime(examRecord.getCommitTime())
                    .examName(examIdMap.get(examRecord.getExamId()).getExamName())
                    .isFinalExam(examIdMap.get(examRecord.getExamId()).getIsFinalExam())
                    .build());
        }
        return PageResult.build(examRecordVOS, examRecordMapper.getExamHistoryTotal(userId));
    }

    @Override
    public ExamResult getExamResult(Long examRecordId) {
        if (examRecordMapper.selectById(examRecordId) == null){
            throw new ExamNotFoundException("考试记录不存在");
        }

        return mongoTemplate.findOne(new Query(new Criteria("_id").is(examRecordId)), ExamResult.class);
    }

    @Override
    public PageResult<Exam4tVO> getExamListVO4t(Integer pageNum, Integer pageSize, Long courseId) {
        ArrayList<Exam> exams = examMapper.getExamList((pageNum-1)*pageSize,pageSize, courseId);
        if (exams.isEmpty()) throw new BaseException("无考试");
        ArrayList<Exam4tVO> examVOS = new ArrayList<>();
        ArrayList<Long> examIds = new ArrayList<>();
        for (Exam exam:exams){
            examIds.add(exam.getId());
        }

        for (Exam exam:exams){
            Exam4tVO build = Exam4tVO.builder()
                    .id(exam.getId())
                    .examName(exam.getExamName())
                    .courseName(courseMapper.getCourseById(exam.getCourseId()).getCourseName())
                    .teacherName(teacherMapper.selectById(exam.getTeacherId()).getName())
                    .startTime(exam.getStartTime())
                    .endTime(exam.getEndTime())
                    .continueTime(exam.getContinueTime())
                    .status(exam.getStatus())
                    .isFinalExam(exam.getIsFinalExam())
                    .completeNum(examRecordMapper.getCompleteNum(exam.getId()))
                    .noCompleteNum(examRecordMapper.getNoCompleteNum(exam.getId()))
                    .noGradingNum(examRecordMapper.getWaitGrading(exam.getId()))
                    .build();

            examVOS.add(build);
        }
        return PageResult.build(examVOS, examMapper.getExamTotal());
    }
}
